const tokenRegex = /\{([^{}]+)\}/g,
  objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g; // matches .xxxxx or ["xxxxx"] to run over object properties

function replacer(all, key, obj) {
  let res = obj;
  key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) {
    name = name || quotedName;
    if (res) {
      if (name in res) {
        res = res[name];
      }
      typeof res == 'function' && isFunc && (res = res());
    }
  });
  res = (res == null || res == obj ? all : res) + '';

  return res;
}

function format(str, obj) {
  return String(str).replace(tokenRegex, function (all, key) {
    return replacer(all, key, obj);
  });
}

export default {
  HL_USER_PATH: {
    d: 'm {mx}, {my} m 6 0c1.9 0 3.43 1.55 3.43 3.47 0 1.43-.86 2.66-2.09 3.19-.04.15-.05.33-.05.53 0 .22.06.42.18.61H9.4a2.6 2.6 0 0 1 2.6 2.6V12a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-1.6a2.6 2.6 0 0 1 2.6-2.6h2.03c.12-.19.18-.39.18-.6 0-.2-.01-.36-.05-.5a3.46 3.46 0 0 1-2.19-3.23A3.45 3.45 0 0 1 6 0Z',
    heightElements: [1],
    widthElements: [1, 1],
  },
  getScaledPath(rawPath, param: Indexable = {}) {
    // positioning
    // compute the start point of the path
    let mx, my;

    if (param.abspos) {
      mx = param.abspos.x;
      my = param.abspos.y;
    } else {
      mx = param.containerWidth * param.position.mx;
      my = param.containerHeight * param.position.my;
    }

    const coordinates = {}; // map for the scaled coordinates
    if (param.position) {
      // path
      const heightRatio = (param.containerHeight / rawPath.height) * param.yScaleFactor;
      const widthRatio = (param.containerWidth / rawPath.width) * param.xScaleFactor;

      // Apply height ratio
      for (let heightIndex = 0; heightIndex < rawPath.heightElements.length; heightIndex++) {
        coordinates['y' + heightIndex] = rawPath.heightElements[heightIndex] * heightRatio;
      }

      // Apply width ratio
      for (let widthIndex = 0; widthIndex < rawPath.widthElements.length; widthIndex++) {
        coordinates['x' + widthIndex] = rawPath.widthElements[widthIndex] * widthRatio;
      }
    }

    // Apply value to raw path
    const path = format(rawPath.d, {
      mx: mx,
      my: my,
      e: coordinates,
    });

    return path;
  },
};
